package com.suntoon.framework.component;

import com.suntoon.framework.common.response.ResultBO;
import com.suntoon.framework.exception.MessageCenterException;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * @Author: LEAVES
 * @Version 1.0
 * @Date: 2021年06月21日 15时37分53秒
 * @Description: 全局异常aop处理
 */
@Component
@Aspect
public class ExceptionHandleAspect {
    private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionHandleAspect.class);

    //此处基于自身项目的路径做具体的设置
    @Pointcut("execution(public * com.suntoon.framework.controller.*.*(..))")
    public void pointCut() {
    }

    @Before("pointCut()")
    public void doBefore(JoinPoint joinPoint) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes == null) {
            return;
        }
        HttpServletRequest request = attributes.getRequest();
        //url
        LOGGER.info("url={}", request.getRequestURL());
        //method
        LOGGER.info("method={}", request.getMethod());
        //ip
        LOGGER.info("id={}", request.getRemoteAddr());
        //class_method
        LOGGER.info("class_method={}", joinPoint.getSignature().getDeclaringTypeName() + "-->" + joinPoint.getSignature().getName());
        //args[]
        LOGGER.info("args={}", joinPoint.getArgs());
    }

    @Around("pointCut()")
    public ResultBO handlerController(ProceedingJoinPoint proceedingJoinPoint) {
        ResultBO returnVO;
        try {
            //获取方法的执行结果
            Object proceed = proceedingJoinPoint.proceed();
            //如果方法的执行结果是ResultBO，则将该对象直接返回
            if (proceed instanceof ResultBO) {
                returnVO = (ResultBO) proceed;
            } else {
                //否则，就要封装到ResultBO的data中
                returnVO = ResultBO.success(proceed);
            }
        } catch (Throwable throwable) {
            //如果出现了异常，调用异常处理方法将错误信息封装到ResultBO中并返回
            returnVO = handlerException(proceedingJoinPoint, throwable);
        }
        return returnVO;
    }

    /**
     * 异常处理
     *
     * @param pjp 织入点
     * @param e   异常
     * @return 统一结果集对象
     */
    private ResultBO handlerException(ProceedingJoinPoint pjp, Throwable e) {
        ResultBO resultBO;
        if (e instanceof MessageCenterException) {
            MessageCenterException messageCenterException = (MessageCenterException) e;
            LOGGER.error("RuntimeException:方法={}， 参数={}， 异常={}", pjp.getSignature(), pjp.getArgs(), messageCenterException.getMessage());
            if (messageCenterException.getException() != null) {
                LOGGER.error(messageCenterException.getMessage(), e);
            }
            resultBO = ResultBO.fail(messageCenterException);
        } else if (e instanceof RuntimeException) {
            LOGGER.error("RuntimeException:方法={}， 参数={}， 异常={}", pjp.getSignature(), pjp.getArgs(), e.getMessage(), e);
            resultBO = ResultBO.fail("系统出现异常，请稍后再试！");
        } else {
            LOGGER.error("异常:方法={}， 参数={}， 异常={}", pjp.getSignature(), pjp.getArgs(), e.getMessage(), e);
            resultBO = ResultBO.fail("系统出现异常，请稍后再试！");
        }
        return resultBO;
    }

}
